// Copyright 2017 Baidu Inc. All Rights Reserved.
// Author: Chen Xihao (chenxihao@baidu.com)
//
// Description: Media Manager

#include "baidu_media_manager.h"
#include "baidu_media_data_manager.h"
#include "baidu_media_play.h"
#include "baidu_status_reporter.h"
#include "baidu_common_buffer.h"
#include "duer_log.h"
#include "heap_monitor.h"

extern int Image$$ARM_LIB_STACK$$Base;
extern int Image$$RW_IRAM1$$ZI$$Limit;

namespace duer {

MediaManager MediaManager::_s_instance;
bool MediaManager::_s_initialized = false;

static void media_report_status(duer::Object& values) {
    float mdm_send_speed = 0.0;
    char speed_buffer[16];

    const MediaReport& report = get_media_report();
    duer::Object media_status;
    media_status.putInt("play_url_count", report.play_url_count);
    media_status.putInt("invalid_url_count", report.invalid_url_count);
    media_status.putInt("play_url_failed_count", report.play_url_failed_count);
    mdm_speed_get_statistic(&mdm_send_speed);
    snprintf(speed_buffer, sizeof(speed_buffer), "%6.3fKB/S", mdm_send_speed);
    media_status.putString("mdm_send_mp3_speed", speed_buffer);

    values.receiveObject("media_status", media_status.releaseObject());
}


void MediaManager::set_bt_mode()
{
	media_set_bt_mode();
}

void MediaManager::set_uart_mode()
{
	media_set_uart_mode();
}	

void MediaManager::set_bt_name(const unsigned char * name)
{
	media_set_bt_name(name);
}


MediaManager::MediaManager() {
}

MediaManager& MediaManager::instance() {
    return _s_instance;
}

bool MediaManager::initialize() {
    void* default_buffer = NULL;
    size_t size = 0;
    bool free = false;

#ifdef TARGET_UNO_91H
    size = (size_t)&Image$$ARM_LIB_STACK$$Base - (size_t)&Image$$RW_IRAM1$$ZI$$Limit;
    default_buffer = &Image$$RW_IRAM1$$ZI$$Limit;
    DUER_LOGV("Image$$ARM_LIB_STACK$$Base = 0x%0x, Image$$RW_IRAM1$$ZI$$Limit = 0x%0x, size = %d",
        &Image$$ARM_LIB_STACK$$Base, &Image$$RW_IRAM1$$ZI$$Limit, size);
#endif

    if (size < MediaPlayBuffer::DEFAULT_BUFFER_SIZE) {
        size = MediaPlayBuffer::DEFAULT_BUFFER_SIZE;
        default_buffer = MALLOC(size, MEDIA);
        if (default_buffer == NULL) {
            DUER_LOGE("No free memory!");
            return false;
        }
        free = true;
    }

    IBuffer* buffer = NEW(MEDIA) CommonBuffer(default_buffer, size, free);
    if (buffer == NULL) {
        DUER_LOGE("No free memory!");
        return false;
    }

    bool ret = initialize(buffer);
    if (!ret) {
        delete buffer;
    }

    return ret;
}

bool MediaManager::initialize(IBuffer* buffer) {
    if (_s_initialized) {
        DUER_LOGI("MediaManager has initialized!");
        return false;
    }

    if (buffer == NULL) {
        DUER_LOGE("initialize failed: invalid argument!");
        return false;
    }

    if (buffer->size() < MediaPlayBuffer::MIN_BUFFER_SIZE) {
        DUER_LOGE("Buffer size must be %d at least!", MediaPlayBuffer::MIN_BUFFER_SIZE);
        return false;
    }

    g_media_play_buffer = NEW(MEDIA) MediaPlayBuffer(buffer);
    start_media_data_mgr_thread();
    start_media_play_thread();
    start_media_voice_thread();
    duer::StatusReporter::obtain().register_report_function(media_report_status);
    _s_initialized = true;

    return true;
}

MediaPlayerStatus MediaManager::play_url(const char* url, bool is_speech,
        bool is_continue_previous) {
    MediaPlayerStatus status = get_media_player_status();
    mdm_send_media_url(url, is_speech, is_continue_previous);
    return status;
}

MediaPlayerStatus MediaManager::play_local(const char* path) {
    MediaPlayerStatus status = get_media_player_status();
    mdm_send_media_file_path(path);
    return status;
}

MediaPlayerStatus MediaManager::play_data(const char* data, size_t size) {
    MediaPlayerStatus status = get_media_player_status();
    mdm_send_media_data(data, size);
    return status;
}



MediaPlayerStatus MediaManager::syn_play_url(const char* url, bool is_speech,bool is_continue_previous) 
{
    MediaPlayerStatus status = get_media_player_status();
    mdm_send_media_url(url, is_speech, is_continue_previous);
	do
	{
		rtos::Thread::wait(100);
		status = get_media_player_status();
	}while(status != MEDIA_PLAYER_IDLE);
	
    return status;
}

MediaPlayerStatus MediaManager::syn_play_local(const char* path) {
    MediaPlayerStatus status = get_media_player_status();
    mdm_send_media_file_path(path);
	do
	{
		rtos::Thread::wait(100);
		status = get_media_player_status();
	}while(status != MEDIA_PLAYER_IDLE);
    return status;
}

MediaPlayerStatus MediaManager::syn_play_data(const char* data, size_t size) {
    MediaPlayerStatus status = get_media_player_status();
    mdm_send_media_data(data, size);
	do
	{
		rtos::Thread::wait(100);
		status = get_media_player_status();
	}while(status != MEDIA_PLAYER_IDLE);
    return status;
}


MediaPlayerStatus MediaManager::pause_or_resume() {
    return mdm_pause_or_resume();
}

int MediaManager::play_previous_continue() 
{
	return play_previous_media_continue();
}

int MediaManager::play_previous_circle() 
{
	return play_previous_media_circle();
}

MediaPlayerStatus MediaManager::stop() {
    return mdm_notify_to_stop();
}

MediaPlayerStatus MediaManager::stop_completely() {
    return mdm_notify_to_stop_completely();
}

MediaPlayerStatus MediaManager::get_media_player_status() {
    return media_play_get_status();
}

int MediaManager::register_listener(MediaPlayerListener* listener) {
    return media_play_register_listener(listener);
}

int MediaManager::unregister_listener(MediaPlayerListener* listener) {
    return media_play_unregister_listener(listener);
}

void MediaManager::set_volume(unsigned char vol) {
    media_play_set_volume(vol);
}

unsigned char MediaManager::get_volume() {
	return media_play_get_volume();
}

void MediaManager::get_download_progress(size_t* total_size, size_t* recv_size) {
    mdm_get_download_progress(total_size, recv_size);
}

void MediaManager::seek(int position) {
    mdm_seek_media(position);
}

} // namespace duer
